﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "UiPlatformUtils.h"

#include "IApplication.h"
#include "IUiDocumentViewManager.h"
#include "IMainWindow.h"
#include "IUiDocument.h"
#include "IUiView.h"
#include "IDocument.h"
#include "IModelView.h"
#include "Vector3dUtils.h"
#include "PropertyPalette.h"
#include "IModelViewDlg.h"
#include "ModelViewDlgUtils.h"
#include "IUIConfiguration.h"

#include "IFamily.h"
#include "ICategory.h"
#include "FileUtility.h"
#include "IInstanceType.h"
#include "IFamilyConfigElement.h"
#include "FilePath.h"
#include "UiCommonDialog.h"
#include "GcmpCommandNames.h"
#include "IRibbon.h"
#include "NewGbmpFlag.h"

#include "FamilyLoadOptionsWithUI.h"
#include "FamilyUtils.h"
#include "GcmpBuiltInCategoryUniIdentities.h"
#include "IGenericType.h"
#include "ILinkElementProxy.h"
#include "ICommandManager.h"
#include "UserTransactionUtils.h"
#include "UiTransactionErrorProcessor.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

void UiPlatformUtils::DefineFunctionForBindingDllDependency()
{

}

void UiPlatformUtils::PrepareUiForNewDocument(gcmp::IDocument * pDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc为空！",L"GDMPLab",L"2024-03-30");
    IMainWindow* pUIMainWnd = IMainWindow::GetMainWindow();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUIMainWnd, L"pUIMainWnd为空！",L"GDMPLab",L"2024-03-30");
    IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewMgr, L"pUiDocViewMgr为空",L"GDMPLab",L"2024-03-30");

    // 找到一个合适的视图并在界面上打开
    OwnerPtr<ElementFilterExceptFamilyAndType> filter = NEW_AS_OWNER_PTR(ElementFilterExceptFamilyAndType);
    std::vector<IElement*> modelViewPtrs = pDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_MODEL_VIEW, filter.get());
    IModelView* pModelView = nullptr;
    if (modelViewPtrs.size() > 0)
    {
        pModelView = quick_cast<IModelView>(modelViewPtrs[0]);
    }
    for (int loop = 0; loop < modelViewPtrs.size(); ++loop)
    {
        if (modelViewPtrs[loop] == nullptr)
            continue;

        // 优先打开平面视图
        IModelView* pModelViewTemp = quick_cast<IModelView>(modelViewPtrs[loop]);
        if (pModelViewTemp)
        {
            double topOffset = 0.0, cutOffset = 0.0, bottomOffset = 0.0, deepOffset = 0.0;
            bool hasTopPlane = pModelViewTemp->GetTopPlaneOffset(topOffset);
            bool hasCutPlane = pModelViewTemp->GetCutPlaneOffset(cutOffset);
            bool hasBottomPlane = pModelViewTemp->GetBottomPlaneOffset(bottomOffset);
            bool hasDeepPlane = pModelViewTemp->GetDeepPlaneOffset(deepOffset);
            if( hasTopPlane && hasCutPlane && hasBottomPlane && hasDeepPlane 
                && Vector3dUtils::IsEqual(pModelViewTemp->GetViewDirection(), Vector3d::NegaUnitZ))
            {
                pModelView = pModelViewTemp;
                break;
            }
        }
    }
    DBG_WARN_AND_RETURN_VOID_UNLESS(pModelView, L"文档中没有ModelView！",L"GDMPLab",L"2024-03-30");

    // 新建视图
    IUiDocument* pUIDoc = pUiDocViewMgr->CreateUiDocument(pDoc);

    // 显示视图管理器。
    ModelViewDlgUtils::DisplayPanel(GBMP_MODELVIEW_DLG_NAME, pUIDoc);
    PropertyPalette::DisplayPanel();//显示属性面板
  
    
    // 解决日志新建旧版本文档
    if (!NewGbmpFlag::IsNewGbmp())
    {
        std::wstring modifyCommandId = ID_CMD_MODIFY;
        pUiDocViewMgr->SetUiViewDefaultActionCommandId(modifyCommandId);
    }
    IUiView* pView = pUIMainWnd->CreateOrOpenUiView(pUIDoc->GetId(), pModelView->GetElementId(), false, L"");

    if (IMPLEMENTATION(IUIConfiguration))
    {
        std::wstring defaultPageName = IMPLEMENTATION(IUIConfiguration)->GetDefaultRibbonPageName(pDoc);
        pUIMainWnd->GetRibbon()->ActivatePage(defaultPageName);
    }

    //进入到默认工具
    DBG_WARN_AND_RETURN_VOID_UNLESS(pUiDocViewMgr->GetCurrentUiView(), L"pUiDocViewMgr->GetCurrentUiView() is nullptr",L"GDMPLab",L"2024-03-30");
    // ActionManager::SendCommand(pUiDocViewMgr->GetCurrentUiView()->GetDefaultActionCommand());
    ICommandManager* pCommandMgr = ICommandManager::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pCommandMgr, L"pCommandMgr is nullptr",L"GDMPLab",L"2024-03-30");
    pCommandMgr->SendCommand(pUiDocViewMgr->GetCurrentUiView()->GetDefaultActionCommand());
}

void UiPlatformUtils::PrepareUI(gcmp::IDocument* pDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDoc, L"pDoc is nullptr",L"GDMPLab",L"2024-03-30");
    // 设置UI层的一些回调
    UserTransactionUtils::SetTransactionErrorProcessor(pDoc, NEW_AS_OWNER_PTR(UiTransactionErrorProcessor));

    //TIMER_START(MODEL_VIEW_OPEN_OR_CREATE);
    // 加载上次保存文档时的Model View。
    std::vector<IElement*> modelViews = pDoc->GetElementsByCategory(BuiltInCategoryUniIdentities::BICU_MODEL_VIEW);
    DBG_WARN_UNLESS(!modelViews.empty(), L"DB Document中没有ModelView！",L"GDMPLab",L"2024-03-30");
    std::sort(modelViews.begin(), modelViews.end(), [](IElement* lhs, IElement* rhs) { return lhs->GetElementId() < rhs->GetElementId(); });

    // 默认打开一个Model View
    if (!modelViews.empty())
    {
        ElementId modelViewToOpen = modelViews[0]->GetElementId();
        IMainWindow* pUIMainWnd = IMainWindow::GetMainWindow();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUIMainWnd, L"MainWnd为空",L"GDMPLab",L"2024-03-30");
        // 新建视图。
        IUiDocumentViewManager* pUiDocViewMgr = IUiDocumentViewManager::Get();
        if (!pUiDocViewMgr)
            return;
        IUiDocument* pUIDoc = nullptr;
        std::vector<IUiDocument*>  pUIDocs = pUiDocViewMgr->GetAllUiDocuments();
        for (auto& pUiDocFind : pUIDocs)
        {
            if (pUiDocFind->GetDbDocument() && pUiDocFind->GetDbDocument()->GetRuntimeId() == pDoc->GetRuntimeId())
            {
                pUIDoc = pUiDocFind;
            }
        }
        if (!pUIDoc)
        {
            pUIDoc = pUiDocViewMgr->CreateUiDocument(pDoc);
        }
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUIDoc, L"pUIDoc为空",L"GDMPLab",L"2024-03-30");
        // 恢复上次文档状态
        ElementId lastTimeView;
        if (pUiDocViewMgr->GetLastOpenedModelViewId(pUIDoc->GetId(), lastTimeView))
        {
            if (lastTimeView.IsValid())
            {
                auto itr = std::find_if(modelViews.begin(), modelViews.end(), [=](IElement* pElem) {
                    if (pElem->GetElementId() == lastTimeView) {
                        return true;
                    }
                    return false;
                });
                if (itr != modelViews.end())
                {
                    modelViewToOpen = lastTimeView;
                }
            }
        }
        //UIDocViewConfig docConfig(pUIDoc);
        //if (docConfig.ReadDocumentState())
        //{
        //    ElementId lastTimeView = docConfig.GetDocumentStateConfig().GetCurModelViewId();
        //    if (lastTimeView.IsValid())
        //    {
        //        auto itr = std::find_if(modelViews.begin(), modelViews.end(), [=](IElement* pElem) {
        //            if (pElem->GetElementId() == lastTimeView) {
        //                return true;
        //            }
        //            return false;
        //        });
        //        if (itr != modelViews.end())
        //        {
        //            modelViewToOpen = lastTimeView;
        //        }
        //    }
        //}

        PropertyPalette::DisplayPanel();//显示属性面板
                                        // 显示视图管理器。
        ModelViewDlgUtils::DisplayPanel(GBMP_MODELVIEW_DLG_NAME, pUIDoc);

        pUIMainWnd->CreateOrOpenUiView(pUIDoc->GetId(), modelViewToOpen, false, L"");
        //TIMER_END(MODEL_VIEW_OPEN_OR_CREATE);

        IRibbon* pUIRibbon = pUIMainWnd->GetRibbon();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pUIRibbon, L"pUIRibbon为空？",L"GDMPLab",L"2024-03-30");
        if (IUIConfiguration* pIUIConfiguration = IMPLEMENTATION(IUIConfiguration))
        {
            std::wstring defaultPageName = pIUIConfiguration->GetDefaultRibbonPageName(pDoc);
            pUIRibbon->ActivatePage(defaultPageName);
        }

        //进入到默认工具
        IUiView* pCurrentUiView = pUiDocViewMgr->GetCurrentUiView();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCurrentUiView, L"pCurrentUiView为空？",L"GDMPLab",L"2024-03-30");
        ICommandManager* pCommandManager = ICommandManager::Get();
        DBG_WARN_AND_RETURN_VOID_UNLESS(pCommandManager, L"pCommandManager为空？",L"GDMPLab",L"2024-03-30");
        pCommandManager->SendCommand(pCurrentUiView->GetDefaultActionCommand());
    }
}

bool UiPlatformUtils::GetFamilyLoadStrategy(gcmp::IDocument* pDoc, const std::wstring& filePathName, gcmp::FamilyFoundStrategy* pStrategy)
{
    DBG_WARN_AND_RETURN_UNLESS(pDoc, false, L"pDoc为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_UNLESS(pStrategy, false, L"输出参数Strategy指针为空",L"GDMPLab",L"2024-03-30");

    std::wstring realFilePathName = filePathName;
    FilePath familyFilePath(realFilePathName);
    const IFamilyConfigElement* pFamilyConfigElement = IFamilyConfigElement::GetFamilyConfigElementByName(pDoc, familyFilePath.GetFileNameWithoutExtension());
    if (pFamilyConfigElement)
    {
        UiCommonDialog::ButtonType rt = UiCommonDialog::ShowMessageBox(GBMP_TR(L"载入构件"), GBMP_TR(L"构件已被载入，是否覆盖？"),
            (int)UiCommonDialog::ButtonType::Yes | (int)UiCommonDialog::ButtonType::No | (int)UiCommonDialog::ButtonType::Cancel);

        if (rt == UiCommonDialog::ButtonType::Cancel)
        {
            return false;
        }

        if (pStrategy)
        {
            *pStrategy = (rt == UiCommonDialog::ButtonType::Yes) ? gcmp::FamilyFoundStrategy::FF_Overwrite : gcmp::FamilyFoundStrategy::FF_Create;
        }
    }

    return true;
}

bool UiPlatformUtils::LoadFamily(gcmp::IDocument * pDoc, const std::wstring& familyFilePath, std::wstring& errorMsg)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    gcmp::FamilyFoundStrategy strategy = gcmp::FamilyFoundStrategy::FF_Create;
    bool bOk = UiPlatformUtils::GetFamilyLoadStrategy(pDoc, familyFilePath, &strategy);
    if (!bOk)
    {
        errorMsg = GBMP_TR(L"获取加载策略失败");
        return false;
    }

    FamilyLoadOptionsWithUI familyLoadOptionsImpl(strategy);
    IFamily* pFamily = quick_cast<IFamily>(gcmp::FamilyUtils::LoadFamily(pDoc, familyFilePath, errorMsg, &familyLoadOptionsImpl));
    if (!pFamily)
        return false;

    return true;
}

bool gcmp::UiPlatformUtils::LoadFamilyInCloud(gcmp::IDocument * pDoc, const LoadFamilyInfos& loadFamilyInfos, std::wstring& errorMsg, LoadFamilyResult* pLoadFamilyResult)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    gcmp::FamilyFoundStrategy strategy = gcmp::FamilyFoundStrategy::FF_Overwrite;

    FamilyLoadOptionsWithUI familyLoadOptionsImpl(strategy);

    IFamily* pFamily = gcmp::FamilyUtils::LoadFamily(pDoc, loadFamilyInfos, errorMsg, &familyLoadOptionsImpl, pLoadFamilyResult);

    if (!pFamily)
        return false;

    return true;
}

bool UiPlatformUtils::RenameFamily(IDocument* pDoc, const std::wstring& oldFamilyName, const std::wstring& newFamilyName)
{
    return FamilyUtils::RenameFamily(pDoc, oldFamilyName, newFamilyName);
}

bool UiPlatformUtils::SaveFamilyFileAs(IDocument* pDoc, const std::wstring& familyName, const std::wstring& newFamilyFilePath)
{
    return FamilyUtils::SaveFamilyFileAs(pDoc, familyName, newFamilyFilePath);
}

std::vector<const IInstance*> UiPlatformUtils::GetFamilyInstances(gcmp::IDocument * pDoc, const std::wstring& familyName)
{
    std::vector<const gcmp::IInstance*> allInstances;

    IFamily* family = IFamily::GetFamilyByName(pDoc, familyName);
    if (family)
    {
        auto types = family->GetInstanceTypes();
        FOR_EACH(type, types)
        {
            const std::vector<IInstance*>& instances = type->GetAllInstances();
            allInstances.insert(allInstances.end(), instances.begin(), instances.end());
        }
    }

    return allInstances;
}

bool UiPlatformUtils::DeleteFamily(gcmp::IDocument * pDoc, const std::wstring& familyName)
{
    return FamilyUtils::DeleteFamily(pDoc, familyName);
}

//////////////////////////////////////////////////////////////////////////
//
bool ElementFilterExceptFamilyAndType::PassesFilter(const IElement* pElement) const
{
    //临时逻辑，为了通过脚本。
    //在事务外创建GenericType的bug修复后删除
    const IGenericType* tempGType = quick_cast<IGenericType>(pElement);
    if (tempGType)
    {
        return false;
    }

    const IType* pType = quick_cast<IType>(pElement);
    const IFamily* pFamily = quick_cast<IFamily>(pElement);
    if (pType || pFamily)
        return false;

    if (quick_cast<ILinkElementProxy>(pElement))
        return false;
    return true;
}
